const { User } = require('@models');
const { generateMiniappToken } = require('@shared/utils/jwt');
const axios = require('axios');
const wxConfig = require('@config/wx');
const envConfig = require('@config/env');
const crypto = require('crypto');

// 获取当前环境
const env = envConfig.NODE_ENV || 'development';
const config = envConfig[env];

// 存储验证码的缓存 (实际生产环境应使用Redis等缓存系统)
const codeCache = {};

/**
 * 小程序微信登录
 * 接收code和用户信息，处理登录流程
 * @param {Object} req - 请求对象
 * @param {Object} res - 响应对象
 */
exports.wxLogin = async (req, res) => {
  try {
    const { code, userInfo, appid } = req.body;
    console.log('[wxLogin] 收到登录请求:', { code, userInfo, appid });

    if (!code) {
      console.error('[wxLogin] 缺少必要参数code');
      return res.status(400).json({
        code: 400,
        message: '缺少必要参数code'
      });
    }

    // 使用前端传入的appId或默认配置的appId
    const appId = appid || wxConfig.miniapp.appId;
    console.log('[wxLogin] 使用的appId:', appId);
    console.log('[wxLogin] 配置中的appSecret:', wxConfig.miniapp.appSecret);
    
    if (!appId) {
      console.error('[wxLogin] 缺少必要参数appid');
      return res.status(400).json({
        code: 400,
        message: '缺少必要参数appid'
      });
    }

    // 1. 调用微信接口，使用code换取openid和session_key
    let wxResult;
    try {
      console.log('[wxLogin] 开始调用微信接口获取openid');
      const requestUrl = 'https://api.weixin.qq.com/sns/jscode2session';
      
      // 从环境变量中获取appSecret，注意环境变量名是MINIAPP_SECRET而不是MINIAPP_APP_SECRET
      const appSecret = process.env.MINIAPP_SECRET || wxConfig.miniapp.appSecret;
      console.log('[wxLogin] 请求URL:', requestUrl);
      console.log('[wxLogin] 请求参数:', {
        appid: appId,
        secret: appSecret,
        js_code: code,
        grant_type: 'authorization_code'
      });

      wxResult = await axios.get(requestUrl, {
        params: {
          appid: appId,
          secret: appSecret,
          js_code: code,
          grant_type: 'authorization_code'
        }
      });

      console.log('[wxLogin] 微信接口返回结果:', wxResult.data);

      if (wxResult.data.errcode) {
        console.error('[wxLogin] 微信登录失败:', wxResult.data);
        return res.status(400).json({
          code: 400,
          message: '微信登录失败: ' + wxResult.data.errmsg
        });
      }
    } catch (error) {
      console.error('[wxLogin] 调用微信接口失败:', error);
      console.error('[wxLogin] 失败详情:', error.response || error.message);
      
      // 在开发环境下，使用模拟数据继续流程
      if (env === 'development') {
        console.log('[wxLogin] 开发环境下使用模拟openid继续流程');
        wxResult = { 
          data: { 
            openid: 'mock_openid_' + new Date().getTime(),
            session_key: 'mock_session_key'
          }
        };
      } else {
        return res.status(500).json({
          code: 500,
          message: '调用微信接口失败'
        });
      }
    }

    const { openid, session_key, unionid } = wxResult.data;
    console.log('[wxLogin] 成功获取openid:', openid);

    // 2. 检查数据库中是否已有该openid的用户
    let user = await User.findOne({ where: { openid } });
    console.log('[wxLogin] 数据库查询结果:', user ? '用户已存在' : '用户不存在');

    if (user) {
      // 3. 如果用户已存在，更新用户信息
      if (userInfo) {
        console.log('[wxLogin] 更新用户信息:', userInfo);
        try {
          await user.update({
            nickname: userInfo.nickname || user.nickname,
            avatar: userInfo.avatar || user.avatar,
            gender: userInfo.gender !== undefined ? userInfo.gender : user.gender,
            country: userInfo.country || user.country,
            province: userInfo.province || user.province,
            city: userInfo.city || user.city,
            last_login_time: new Date()
          });
          console.log('[wxLogin] 用户信息更新成功');
        } catch (updateError) {
          console.error('[wxLogin] 用户信息更新失败:', updateError);
          // 继续流程，不中断登录
        }
      } else {
        // 仅更新登录时间
        console.log('[wxLogin] 仅更新登录时间');
        try {
          await user.update({
            last_login_time: new Date()
          });
        } catch (updateError) {
          console.error('[wxLogin] 更新登录时间失败:', updateError);
          // 继续流程，不中断登录
        }
      }
    } else {
      // 4. 如果用户不存在，创建新用户
      const userData = {
        openid,
        unionid: unionid || null,
        status: 1,
        last_login_time: new Date()
      };

      // 添加用户信息（如果有）
      if (userInfo) {
        console.log('[wxLogin] 创建新用户，用户信息:', userInfo);
        Object.assign(userData, {
          nickname: userInfo.nickname || `微信用户`,
          avatar: userInfo.avatar || null,
          gender: userInfo.gender !== undefined ? userInfo.gender : 0,
          country: userInfo.country || null,
          province: userInfo.province || null,
          city: userInfo.city || null
        });
      }

      console.log('[wxLogin] 创建用户数据:', userData);
      try {
        user = await User.create(userData);
        console.log('[wxLogin] 用户创建成功，ID:', user.id);
      } catch (createError) {
        console.error('[wxLogin] 用户创建失败:', createError);
        return res.status(500).json({
          code: 500,
          message: '创建用户失败'
        });
      }
    }

    // 5. 生成token
    const token = generateMiniappToken(user);
    console.log('[wxLogin] 生成token成功');

    // 刷新用户数据
    try {
      user = await User.findByPk(user.id);
      console.log('[wxLogin] 最终用户数据:', user.toJSON());
    } catch (findError) {
      console.error('[wxLogin] 刷新用户数据失败:', findError);
      // 使用现有的user继续
    }

    // 6. 返回用户信息和token
    const response = {
      code: 200,
      message: '登录成功',
      data: {
        token,
        user: {
          id: user.id,
          nickname: user.nickname,
          avatar: user.avatar,
          gender: user.gender,
          phone: user.phone,
          status: user.status
        }
      }
    };
    console.log('[wxLogin] 返回响应:', response);
    return res.json(response);
  } catch (error) {
    console.error('[wxLogin] 微信登录处理失败:', error);
    return res.status(500).json({
      code: 500,
      message: '服务器内部错误'
    });
  }
};

/**
 * 发送手机验证码
 * @param {Object} req - 请求对象
 * @param {Object} res - 响应对象
 */
exports.sendVerifyCode = async (req, res) => {
  try {
    const { phone } = req.body;

    if (!phone) {
      return res.status(400).json({
        code: 400,
        message: '手机号不能为空'
      });
    }

    // 验证手机号格式
    if (!/^1[3-9]\d{9}$/.test(phone)) {
      return res.status(400).json({
        code: 400,
        message: '手机号格式不正确'
      });
    }

    // 生成6位随机验证码
    const code = Math.floor(100000 + Math.random() * 900000).toString();
    
    // 存储验证码到缓存，有效期10分钟
    codeCache[phone] = {
      code: code,
      expireAt: new Date(Date.now() + 10 * 60 * 1000) // 10分钟后过期
    };

    // 在实际应用中，这里应该调用短信服务发送验证码
    console.log(`向手机号 ${phone} 发送验证码: ${code}`);

    // 返回成功
    return res.json({
      code: 200,
      message: '验证码发送成功'
    });
  } catch (error) {
    console.error('发送验证码失败:', error);
    return res.status(500).json({
      code: 500,
      message: '服务器内部错误'
    });
  }
};

/**
 * 手机号验证码登录
 * @param {Object} req - 请求对象
 * @param {Object} res - 响应对象
 */
exports.phoneLogin = async (req, res) => {
  try {
    const { phone, code } = req.body;

    if (!phone || !code) {
      return res.status(400).json({
        code: 400,
        message: '手机号和验证码不能为空'
      });
    }

    // 验证手机号格式
    if (!/^1[3-9]\d{9}$/.test(phone)) {
      return res.status(400).json({
        code: 400,
        message: '手机号格式不正确'
      });
    }

    // 验证验证码
    const cacheItem = codeCache[phone];
    if (!cacheItem || cacheItem.code !== code) {
      return res.status(400).json({
        code: 400,
        message: '验证码错误'
      });
    }

    // 检查验证码是否过期
    if (cacheItem.expireAt < new Date()) {
      // 删除过期的验证码
      delete codeCache[phone];
      
      return res.status(400).json({
        code: 400,
        message: '验证码已过期'
      });
    }

    // 验证通过，删除缓存中的验证码
    delete codeCache[phone];

    // 查询数据库中是否已存在该手机号的用户
    let user = await User.findOne({ where: { phone } });

    if (!user) {
      // 用户不存在，创建新用户
      user = await User.create({
        phone,
        nickname: `用户${phone.slice(-4)}`,
        status: 1,
        last_login_time: new Date()
      });
    } else {
      // 用户存在，更新登录时间
      await user.update({
        last_login_time: new Date()
      });
    }

    // 生成token
    const token = generateMiniappToken(user);

    // 返回用户信息和token
    return res.json({
      code: 200,
      message: '登录成功',
      data: {
        token,
        user: {
          id: user.id,
          nickname: user.nickname,
          avatar: user.avatar,
          phone: user.phone,
          gender: user.gender,
          status: user.status
        }
      }
    });
  } catch (error) {
    console.error('手机号登录失败:', error);
    return res.status(500).json({
      code: 500,
      message: '服务器内部错误'
    });
  }
};

/**
 * 微信登录并获取手机号
 * @param {Object} req - 请求对象
 * @param {Object} res - 响应对象
 */
exports.wxPhoneLogin = async (req, res) => {
  try {
    const { code, encryptedData, iv, userInfo } = req.body;

    if (!code || !encryptedData || !iv) {
      return res.status(400).json({
        code: 400,
        message: '参数不完整'
      });
    }

    // 1. 调用微信接口，获取session_key和openid
    let wxResult;
    try {
      wxResult = await axios.get('https://api.weixin.qq.com/sns/jscode2session', {
        params: {
          appid: wxConfig.miniapp.appId,
          secret: wxConfig.miniapp.appSecret,
          js_code: code,
          grant_type: 'authorization_code'
        }
      });

      if (wxResult.data.errcode) {
        console.error('微信登录失败:', wxResult.data);
        return res.status(400).json({
          code: 400,
          message: '微信登录失败: ' + wxResult.data.errmsg
        });
      }
    } catch (error) {
      console.error('调用微信接口失败:', error);
      return res.status(500).json({
        code: 500,
        message: '调用微信接口失败'
      });
    }

    const { openid, session_key, unionid } = wxResult.data;

    // 2. 解密手机号信息
    let phoneInfo;
    try {
      // 对称解密使用的算法为 AES-128-CBC，数据采用PKCS#7填充
      const crypted = Buffer.from(encryptedData, 'base64');
      const key = Buffer.from(session_key, 'base64');
      const aesIv = Buffer.from(iv, 'base64');
      
      const decipher = crypto.createDecipheriv('aes-128-cbc', key, aesIv);
      decipher.setAutoPadding(true);
      
      let decoded = decipher.update(crypted, 'binary', 'utf8');
      decoded += decipher.final('utf8');
      
      phoneInfo = JSON.parse(decoded);
      
      if (!phoneInfo.phoneNumber) {
        return res.status(400).json({
          code: 400,
          message: '获取手机号失败'
        });
      }
    } catch (error) {
      console.error('解密手机号失败:', error);
      return res.status(400).json({
        code: 400,
        message: '解密手机号失败'
      });
    }

    // 3. 查询或创建用户
    let user = await User.findOne({
      where: {
        openid
      }
    });

    if (user) {
      // 用户存在，更新信息
      await user.update({
        phone: phoneInfo.phoneNumber,
        nickname: userInfo?.nickname || user.nickname,
        avatar: userInfo?.avatar || user.avatar,
        gender: userInfo?.gender !== undefined ? userInfo.gender : user.gender,
        country: userInfo?.country || user.country,
        province: userInfo?.province || user.province,
        city: userInfo?.city || user.city,
        last_login_time: new Date()
      });
    } else {
      // 用户不存在，创建新用户
      user = await User.create({
        openid,
        unionid: unionid || null,
        phone: phoneInfo.phoneNumber,
        nickname: userInfo?.nickname || `用户${phoneInfo.phoneNumber.slice(-4)}`,
        avatar: userInfo?.avatar || null,
        gender: userInfo?.gender || 0,
        country: userInfo?.country || null,
        province: userInfo?.province || null,
        city: userInfo?.city || null,
        status: 1,
        last_login_time: new Date()
      });
    }

    // 4. 生成token
    const token = generateMiniappToken(user);

    // 5. 返回结果
    return res.json({
      code: 200,
      message: '登录成功',
      data: {
        token,
        user: {
          id: user.id,
          nickname: user.nickname,
          avatar: user.avatar,
          phone: user.phone,
          gender: user.gender,
          status: user.status
        }
      }
    });
  } catch (error) {
    console.error('微信手机号登录失败:', error);
    return res.status(500).json({
      code: 500,
      message: '服务器内部错误'
    });
  }
};

/**
 * 获取当前登录用户信息
 * @param {Object} req - 请求对象
 * @param {Object} res - 响应对象
 */
exports.getUserInfo = async (req, res) => {
  try {
    // 用户信息已通过中间件附加到req.user
    const user = await User.findByPk(req.user.id);
    
    if (!user) {
      return res.status(404).json({
        code: 404,
        message: '用户不存在'
      });
    }

    // 返回用户信息
    return res.json({
      code: 200,
      message: '获取成功',
      data: {
        id: user.id,
        nickname: user.nickname,
        avatar: user.avatar,
        gender: user.gender,
        phone: user.phone,
        status: user.status
      }
    });
  } catch (error) {
    console.error('获取用户信息失败:', error);
    return res.status(500).json({
      code: 500,
      message: '服务器内部错误'
    });
  }
};

// 更新用户信息
exports.updateUserInfo = async (req, res) => {
  try {
    const user = req.user;
    const { nickname, avatar, gender, phone } = req.body;
    
    if (!user) {
      return res.json(ApiResponse.unauthorized('未登录'));
    }
    
    // 更新用户信息
    await user.update({
      nickname: nickname || user.nickname,
      avatar: avatar || user.avatar,
      gender: gender !== undefined ? gender : user.gender,
      phone: phone || user.phone
    });
    
    return res.json(ApiResponse.success({
      id: user.id,
      nickname: user.nickname,
      avatar: user.avatar,
      gender: user.gender,
      phone: user.phone
    }));
  } catch (error) {
    console.error('更新用户信息失败:', error);
    return res.json(ApiResponse.error('更新用户信息失败'));
  }
}; 